using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using Microsoft.SPOT.Presentation;

#if MINI
using SecretLabs.NETMF.Hardware.NetduinoMini;
#else
using SecretLabs.NETMF.Hardware.Netduino;
#endif

namespace codebase
{
    public class _4DSPE_NDSTS_Demo
    {
        #region Variables

        static FourDSPE gfx = new FourDSPE();
        static NDSTouchscreen nds = null;
        static Point point = new Point();

        static long lasttick = DateTime.Now.Ticks / 10000;
        static int _fps = 0;
        static int fps = 0;
        #endregion

        #region Main, Update, Draw

        public static void Run()
        {
            Initialize();

            demoRGB();

            initMedia();

            demoVideo();

            //gfx.TextHeight(2);
            
            createGUI();

            while (true)
            {
                Update();
                _fps++;

                long now = DateTime.Now.Ticks / 10000;
                if (now - lasttick >= 1000)
                {
                    fps = _fps;
                    _fps = 0;
                    lasttick = now;

                    Draw();
                }
            }
        }

        static void Initialize()
        {
#if MINI
            gfx.Initialize(SerialPorts.COM1, 115200, Pins.GPIO_PIN_10);
#else
            gfx.Initialize(SerialPorts.COM2, 9600, Pins.GPIO_PIN_D4);
            gfx.SetBaudRate((int)SPE.BAUD115200, 115200);
#endif

#if PICASO
            gfx.TouchEnable();

            gfx.SetFont((int)SPE.FONT1);
#else
#if MINI
            nds = new NDSTouchscreen(Pins.GPIO_PIN_20, Pins.GPIO_PIN_19, Pins.GPIO_PIN_18, Pins.GPIO_PIN_17,
                AnalogChannels.ANALOG_PIN_5,AnalogChannels.ANALOG_PIN_6,
                gfx.Width, gfx.Height);
#else
            nds = new NDSTouchscreen(Pins.GPIO_PIN_D5, Pins.GPIO_PIN_D6, Pins.GPIO_PIN_D7, Pins.GPIO_PIN_D8,
                AnalogChannels.ANALOG_PIN_A0,AnalogChannels.ANALOG_PIN_A1,
                gfx.Width, gfx.Height);
#endif

#endif
        }

        static void Update()
        {
            moveColors();
            checkTouchScreen();
        }

        static void Draw()
        {
            updateXY();
            updateGraphs();
            updateDebug();
        }

        static void checkTouchScreen()
        {
#if PICASO
            point = gfx.TouchScan();
            if (gfx.isTouchDown && trail && point != null) gfx.DrawFilledCircle(point.x, point.y, 2, ColorExtensions.RGB16(br, bg, bb));
#else
            point = nds.Scan();
            if(nds.isTouchDown&&trail&&point!=null)gfx.DrawFilledCircle(point.x, point.y, 2, ColorExtensions.RGB16(br, bg, bb));
#endif
        }

        #endregion

        #region UI

        static UI.WindowManager man;

        static UI.Window windowDebug;
        static UI.Label lMemory;
        static UI.Label lFps;
        static UI.CheckBox lDraw;

        static UI.Window windowMain;
        static UI.ScrollingGraph graph_x;
        static UI.ScrollingGraph graph_y;
        static UI.Label lX;
        static UI.Label lY;
        static UI.Image logo;
        static UI.Button btn1;
        static UI.Button btn2;
        static UI.Button btn3;

        static void createGUI()
        {
            man = new UI.WindowManager(gfx, nds);

            windowMain = man.Add(0,0,10, 10,true);

            logo = (UI.Image)windowMain.Add(UI.Window.ControlTypes.Image,6,16);

            lX = (UI.Label)windowMain.Add(UI.Window.ControlTypes.Label, 1, 2);
            lY = (UI.Label)windowMain.Add(UI.Window.ControlTypes.Label, 1, 3);

            graph_x = (UI.ScrollingGraph)windowMain.Add(UI.Window.ControlTypes.ScrollingGraph, 1, 4);
            graph_y = (UI.ScrollingGraph)windowMain.Add(UI.Window.ControlTypes.ScrollingGraph, 1, 6);
            graph_x.DataGrabberFunction += new UI.ScrollingGraph.DataGrabberDelegate(graph_data_x);
            graph_y.DataGrabberFunction += new UI.ScrollingGraph.DataGrabberDelegate(graph_data_y);
            graph_x.Stop();
            graph_y.Stop();
            graph_x.Start(500);
            graph_y.Start(500);

            btn1 = (UI.Button)windowMain.Add(UI.Window.ControlTypes.Button, 1, 9);
            btn1.Text = "\n 12345 \n";
            btn2 = (UI.Button)windowMain.Add(UI.Window.ControlTypes.Button, 1, 14);
            btn2.Text = "12345";
            btn2.AlternativeRenderer = true;
            btn3 = (UI.Button)windowMain.Add(UI.Window.ControlTypes.Button, 13, 9);
            btn3.Text = "Hallo Welt";
            btn3.NotPressedColor = ColorExtensions.RGB16(100,255,100);
            btn3.PressedColor = ColorExtensions.RGB16(100,100,255);
            btn3.AlternativeRenderer = true;

            windowMain.CaptionText = "Touch Debug";
            windowMain.Redraw();

            windowDebug = man.Add(13, 2, 16, 6,false);

            lMemory = (UI.Label)windowDebug.Add(UI.Window.ControlTypes.Label, 1, 3);
            lFps = (UI.Label)windowDebug.Add(UI.Window.ControlTypes.Label, 1, 2);
            lDraw = (UI.CheckBox)windowDebug.Add(UI.Window.ControlTypes.CheckBox, 1, 4);
            lDraw.Text = "Drawing Test";

            windowDebug.CaptionText = "Debug Data";
            windowDebug.CaptionColor = ColorExtensions.RGB16(200, 110, 140);
            windowDebug.Redraw();

            lDraw.CheckStateChanged += new UI.CheckBox.CheckStateChangedDelegate(click_lDraw);
        }

        #region UI Functions

        static int br = 200;
        static int bg = 50;
        static int bb = 10;
        static bool dirr = true;
        static bool dirg = false;
        static bool dirb = false;

        static void moveColors()
        {
            if (dirr) { br--; } else { br++; }
            if (dirg) { bg--; } else { bg++; }
            if (dirb) { bb--; } else { bb++; }
            if (br > 255 || br < 0) dirr = !dirr;
            if (bg > 200 || bg < 0) dirg = !dirg;
            if (bb > 180 || bb < 0) dirb = !dirb;
        }

        static void updateXY()
        {
            string tx, ty;

            if (point != null)
            {
                tx = point.x.ToString().PadLeft(3, ' ');
                ty = point.y.ToString().PadLeft(3, ' ');
            }
            else
            {
                tx = "  -";
                ty = "  -";
            }

            lX.Text = "X: " + tx;
            lY.Text = "Y: " + ty;
            lX.Refresh();
            lY.Refresh();
        }

        static void updateGraphs()
        {
            if (!trail)
            {
                graph_x.Refresh();
                graph_y.Refresh();
            }
        }

        static void redrawGUI()
        {
            windowMain.Redraw();
            windowDebug.Redraw();
        }

        static void updateDebug()
        {
            lFps.Text = "FPS:" + fps.ToString().PadLeft(4, ' ');
            lFps.BackgroundColor = ColorExtensions.RGB16(br, bg, bb);
            lFps.Refresh();

            lMemory.Text = "RAM: " + Debug.GC(false).ToString();
            lMemory.Refresh();
        }

        #endregion

        #region UI Events

        static int graph_data_x()
        {
            return point == null ? 0 : point.x;
        }

        static int graph_data_y()
        {
            return point == null ? 0 : point.y;
        }

        static bool trail = false;
        static void click_lDraw(Boolean check)
        {
            trail = !trail;

            if (trail)
            {
                graph_x.Stop();
                graph_y.Stop();
            }
            else
            {
                graph_x.Start(200);
                graph_y.Start(200);
            }

            redrawGUI();
        }

        #endregion

        #endregion

        #region Demos

        static OutputPort led1;
        static OutputPort led2;
        static void demoLED()
        {
#if MINI
            led1 = new OutputPort(Pins.GPIO_PIN_9, true);
            led2 = new OutputPort(Pins.GPIO_PIN_14, true);
#else
            led1 = new OutputPort(Pins.GPIO_PIN_D5, true);
            led2 = new OutputPort(Pins.GPIO_PIN_D6, true);
#endif

            led1.Write(false);
            Thread.Sleep(1000);
            led2.Write(false);
        }

        static void initMedia()
        {
            gfx.MediaInit();
        }

        static void demoVideo()
        {
            gfx.SetByteAddress((int)0x00, (int)0x8200);

            for (int i = 400; i < 450; i++)
            {
                gfx.DisplayVideoFrameRAW(0, 0, i);
            }

        }

        static void demoGradient()
        {
            gfx.GradientY(0, 0, 0, 0, 20, 180, gfx.Width, gfx.Height);
        }

        static void demoRGB()
        {
            gfx.BackgroundColor(ColorExtensions.RGB16(255, 0, 0));
            gfx.Clear();

            Thread.Sleep(200);

            gfx.BackgroundColor(ColorExtensions.RGB16(0, 255, 0));
            gfx.Clear();

            Thread.Sleep(200);

            gfx.BackgroundColor(ColorExtensions.RGB16(0, 0, 255));
            gfx.Clear();

            Thread.Sleep(200);
        }
        #endregion
    }
}
